package selector

import (
	"context"
	"errors"
	"math/rand"
	"sync"
	"sync/atomic"
)

// 随机
type RandomBanlance struct {
	nodes    atomic.Value
	curIndex int
	mux      sync.Mutex
}

type RandomBuilder struct {
	r *RandomBanlance
}

func NewRandomBuilder() Builder {
	return &RandomBanlance{}
}

func (r *RandomBanlance) Build() Selector {
	return NewRandomBanlance()
}

func NewRandomBanlance() Selector {
	return &RandomBanlance{
		curIndex: -1,
	}
}

func (r *RandomBanlance) Add(nodes ...Node) error {
	if len(nodes) == 0 {
		return errors.New("params len 1 at least")
	}
	r.mux.Lock()
	defer r.mux.Unlock()
	//可以在赋值之前加一个输入参数正确性判断
	r.nodes.Store(nodes)
	return nil
}

// 随机化负载均衡
func (r *RandomBanlance) Next(ctx context.Context) (selected Node, err error) {
	r.mux.Lock()
	defer r.mux.Unlock()
	n := r.nodes
	if n.Load() == nil {
		return nil, errors.New("NODE_NOT_FOUND")
	}
	nodes := n.Load().([]Node)
	if len(nodes) == 0 {
		return nil, errors.New("node len 0")
	}
	r.curIndex = rand.Intn(len(nodes))
	node := nodes[r.curIndex]
	peer, ok := FromPeerContext(ctx)
	if ok {
		peer.Node = node
	}
	return node, nil
}
